package org.net5ijy.security.dao.hibernate;

import java.util.Date;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.net5ijy.security.bean.PersistentLogin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.authentication.rememberme.PersistentRememberMeToken;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * HibernateTokenRepositoryImpl
 *
 * @author XGF
 * @date 2020/11/30 22:43
 */
@Repository
@Transactional(rollbackFor = RuntimeException.class)
public class HibernateTokenRepositoryImpl implements PersistentTokenRepository {

  @Autowired
  private SessionFactory sessionFactory;

  @Override
  public void createNewToken(PersistentRememberMeToken token) {
    PersistentLogin pl = new PersistentLogin();
    pl.setUsername(token.getUsername());
    pl.setToken(token.getTokenValue());
    pl.setSeries(token.getSeries());
    pl.setLastUsed(token.getDate());
    this.sessionFactory.getCurrentSession().save(pl);
  }

  @Override
  public void updateToken(String series, String tokenValue, Date lastUsed) {
    Session session = this.sessionFactory.getCurrentSession();
    Criteria criteria = session.createCriteria(PersistentLogin.class);
    criteria.add(Restrictions.eq("id", series));

    PersistentLogin persistentLogin = (PersistentLogin) criteria.uniqueResult();
    persistentLogin.setToken(tokenValue);
    persistentLogin.setLastUsed(lastUsed);

    session.merge(persistentLogin);
  }

  @Override
  @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
  public PersistentRememberMeToken getTokenForSeries(String seriesId) {
    Criteria criteria = this.sessionFactory.getCurrentSession()
        .createCriteria(PersistentLogin.class);
    criteria.add(Restrictions.eq("series", seriesId));
    PersistentLogin persistentLogin = (PersistentLogin) criteria.uniqueResult();

    return new PersistentRememberMeToken(persistentLogin.getUsername(),
        persistentLogin.getSeries(), persistentLogin.getToken(),
        persistentLogin.getLastUsed());
  }

  @Override
  public void removeUserTokens(String username) {
    Session session = this.sessionFactory.getCurrentSession();
    Criteria criteria = session.createCriteria(PersistentLogin.class);
    criteria.add(Restrictions.eq("username", username));
    PersistentLogin persistentLogin = (PersistentLogin) criteria.uniqueResult();
    if (persistentLogin != null) {
      session.delete(persistentLogin);
    }
  }
}
